<?php

namespace App\Models\Enroll;

use App\Contracts\Services\Storage\StorageService;
use App\Models\Activity\Activity;
use App\Models\Resource\Resource;
use Illuminate\Container\Container;
use InvalidArgumentException;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;

/**
 * Class Parser
 *
 * @package App\Models\Enroll
 * @property \App\Contracts\Services\Storage\StorageService $storage
 * @property Enroll                                         $enroll;
 */
class Parser
{
    protected $imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp',];
    protected $videoExtensions = ['mp4', 'mov', 'avi', 'rm', 'rmvb', 'ogg'];

    protected $fieldNames = [];
    protected $storage;
    protected $enroll;

    public function __construct(Enroll $enroll)
    {
        if (!$enroll->exists) {
            throw new InvalidArgumentException(
                "Argument \$enroll must be a Model::first() instance, not new Model instance."
            );
        }

        $this->enroll = $enroll;
        $this->storage = Container::getInstance()->make(StorageService::class);
    }

    public function getFieldNames()
    {
        if (empty($this->fieldNames)) {
            $activity = Activity::query()->find($this->enroll->getAttribute('activities_id'));
            $rules = \GuzzleHttp\json_decode($activity->getAttribute('rule'), true);
            $names = [];

            foreach ($rules as $category => $elements) {
                if (!is_array($elements)) {
                    continue;
                }
                foreach ($elements as $of => $element) {
                    $k = $category . '_' . $of;
                    $names[$k] = Arr::get($element, 'value');
                }
            }

            $this->fieldNames = $names;
        }

        return $this->fieldNames;
    }

    public function getName()
    {
        return $this->enroll->getAttribute('name');
    }

    public function getMobile()
    {
        return $this->enroll->getAttribute('mobile');
    }

    public function getPaidAmount()
    {
        return $this->enroll->getAttribute('enrollPay');
    }

    public function getCoverUrl()
    {
        $cover = Arr::first($this->enroll->getAttribute('content'));

        if ($this->isOssUrl($cover)) {
            $cover = $this->storage->toHttpUrl($cover);
        }

        if ($this->isImage($cover)) {
            return $cover;
        }

        return '';
    }

    public function getResourceUrl()
    {
        if ($this->getCoverUrl()) {
            return '';
        }

        return Arr::first($this->enroll->getAttribute('content'));
    }

    public function toCandidateContent($is_filter = true)
    {
        $content = $this->enroll->getAttribute('content');
        $extends = $this->enroll->getAttribute('extfield');
        $name = $this->enroll->getAttribute('name');
        $mobile = $this->enroll->getAttribute('mobile');

        $str = $this->formatBaseInfo($name,$mobile);
        $str .= $this->parseExtends($extends);
        $str .= $this->parseMainContent($content, $is_filter);

        return $str;
    }

    public function parseEnrollsToJson ()
    {
        $name = $this->enroll->getAttribute('name');
        $mobile = $this->enroll->getAttribute('mobile');
        $content = $this->enroll->getAttribute('content');
        $extends = $this->enroll->getAttribute('extfield');

        $base_data = $this->getFormatBaseInfo($name,$mobile);
        $extends_data = $this->getFormatExtends($extends);
        $content_data = $this->getFormatContent($content);

        //array_merge 如果key为数字，将重新索引
        $base_extends_data['text'] = $base_data + $extends_data;
        $format_data = array_merge($base_extends_data,$content_data);

        return json_encode($format_data);
    }

    public function getFormatBaseInfo($name,$mobile)
    {
        return ['姓名'=>$name,'电话'=>$mobile];
    }

    public function getFormatContent(array $contents)
    {
        $arr_content = [];
        foreach ($contents as $key => $file) {
            if ($this->isImage($file)) {
                if ($this->isOssUrl($file)) {
                    $arr_content['img'][] = $this->storage->toHttpUrl($file);
                }
            } elseif ($video = $this->getVideo($file)) {
                $arr_content['video'][] = $video;
            } else {
                $arr_content['text'][] = $file;
            }
        }
        return $arr_content;
    }

    public function getFormatExtends(array $extends) {
        $arr_extends = [];
        foreach ($extends as $field => $values) {
            $field_name = $this->getFieldName($field);
            if (is_array($values)) {
                $arr_extends[$field_name] = implode(',',$values);
            } else {
                $arr_extends[$field_name] = $values;
            }
        }
        return $arr_extends;
    }

    public function formatBaseInfo($name,$mobile)
    {
        $str = '<p><span>姓名：'.$name.'</span></p>';
        $str .= '<p><span>电话：'.$mobile.'</span></p>';
        return $str;
    }
    public function makeExtFields()
    {
        $extends = $this->enroll->getAttribute('extfield');
        $content = [];
        foreach ($extends as $field => $values) {
            $col = $this->getFieldName($field);
            if (is_array($values)) {
                foreach ($values as $value) {
                    if ($this->isOssUrl($value)) {
                        $content[$col] = $this->storage->toHttpUrl($value);
                    } else {
                        $content[$col] = $value;
                    }
                }
            } else {
                $content[$col] = $values;
            }
        }

        return $content;
    }

    protected function parseMainContent(array $contents, $is_filter = true)
    {
        $main = '<div>';

        foreach ($contents as $index => $file) {
            if($is_filter) {
                if (($this->isImage($file) || $this->getVideo($file)) && $index == 0) {
                    continue;
                }
            }
            if ($this->isImage($file)) {
                if ($this->isOssUrl($file)) {
                    $file = $this->storage->toHttpUrl($file);
                }

                $main .= sprintf('<div class="img-container"><img src="%s"></div>', $file);
            } elseif ($video = $this->getVideo($file)) {
                $main .= sprintf(
                    '<div class="video-container"><video src="%s" poster="%s" controls="controls">not support video</video></div>',
                    $video['resource_url'], $video['cover_url']
                );
//                $main .= sprintf('<p><a href="%s" target="_blank">%s</p>', $video, $file);
            } else {
                $main .= sprintf('<p><a  href="%s" target="_blank">%s</p>', $file, $file);
            }
        }

        return $main . '</div>';
    }

    protected function parseExtends(array $extends)
    {
        $content = '<div>';

        foreach ($extends as $field => $values) {
            $content .= '<p >' . $this->getFieldName($field) . ':';

            if (is_array($values)) {
                foreach ($values as $value) {
                    if ($this->isOssUrl($value)) {
                        $file = $this->storage->toHttpUrl($value);

                        if ($this->isImage($file)) {
                            $content .= sprintf('<img src="%s"></p>', $file);
                        } else {
                            $content .= sprintf(
                                '<a  href="%s" target="_blank">%s</a></p>',
                                $file,
                                $file
                            );
                        }
                    } elseif ($this->isUrl($value)) {
                        if ($this->isImage($value)) {
                            $content .= sprintf('<img src="%s"></p>', $value);
                        } else {
                            $content .= sprintf(
                                '<a  href="%s" target="_blank">%s</a></p>',
                                $value,
                                $value
                            );
                        }
                    } else {
                        $content .= sprintf('<span >%s</span>', $value);
                        $content .= '&nbsp;&nbsp;';
                    }
                }
            } else {
                if ($this->isImage($values)) {
                    $content .= sprintf('<p><img src="%s"></p>', $values);
                } elseif ($this->isUrl($values)) {
                    $content .= sprintf(
                        '<p><a  href="%s" target="_blank">%s</a></p>',
                        $values,
                        $values
                    );
                } else {
                    $content .= sprintf('%s</p>', $values);
                }
            }
        }

        return $content . '</div>';
    }

    protected function getFieldName($field)
    {
        return Arr::get($this->getFieldNames(), $field, '');
    }

    protected function isOssUrl($url)
    {
        return Str::startsWith($url, ['alioss://']);
    }

    protected function isUploadField($name)
    {
        return Str::startsWith($name, ['upload_']);
    }

    protected function isImage($filename)
    {
        return Str::endsWith($filename, $this->imageExtensions);
    }

    protected function getVideo($value)
    {
        $query = Resource::query()
            ->where('resource_id', $value);
        if(!$query->count()){
            return [];
        }
        return [
            'resource_url' => $query->value('resource_url'),
            'cover_url'    => $query->value('cover_url'),
        ];
    }

    protected function isUrl($value)
    {
        return filter_var($value, FILTER_VALIDATE_URL);
    }
}
